// $ANTLR 3.0.1 Euclid.g 2008-01-25 16:11:57

package Euclid;


import org.antlr.runtime.*;
import java.util.Stack;
import java.util.List;
import java.util.ArrayList;

public class EuclidParser extends Parser {
    public static final String[] tokenNames = new String[] {
        "<invalid>", "<EOR>", "<DOWN>", "<UP>", "PLUS", "MINUS", "MULT", "DIV", "MOD", "INT_DIV", "LPAREN", "RPAREN", "POW", "NEWLINE", "ID", "INT", "FLOAT", "STRING", "WS", "'='", "'~'", "','"
    };
    public static final int MINUS=5;
    public static final int INT=15;
    public static final int WS=18;
    public static final int EOF=-1;
    public static final int STRING=17;
    public static final int FLOAT=16;
    public static final int RPAREN=11;
    public static final int LPAREN=10;
    public static final int DIV=7;
    public static final int POW=12;
    public static final int MOD=8;
    public static final int PLUS=4;
    public static final int INT_DIV=9;
    public static final int MULT=6;
    public static final int ID=14;
    public static final int NEWLINE=13;

        public EuclidParser(TokenStream input) {
            super(input);
        }
        

    public String[] getTokenNames() { return tokenNames; }
    public String getGrammarFileName() { return "Euclid.g"; }


    public FunctionLibrary f = new FunctionLibrary();



    // $ANTLR start stat
    // Euclid.g:27:1: stat returns [VarType value] : ( expr NEWLINE | ID '=' expr NEWLINE | NEWLINE );
    public final VarType stat() throws RecognitionException {
        VarType value = null;

        Token ID2=null;
        VarType expr1 = null;

        VarType expr3 = null;


        try {
            // Euclid.g:29:2: ( expr NEWLINE | ID '=' expr NEWLINE | NEWLINE )
            int alt1=3;
            switch ( input.LA(1) ) {
            case MINUS:
            case LPAREN:
            case INT:
            case FLOAT:
            case STRING:
            case 20:
                {
                alt1=1;
                }
                break;
            case ID:
                {
                int LA1_2 = input.LA(2);

                if ( ((LA1_2>=PLUS && LA1_2<=MOD)||LA1_2==LPAREN||(LA1_2>=POW && LA1_2<=NEWLINE)) ) {
                    alt1=1;
                }
                else if ( (LA1_2==19) ) {
                    alt1=2;
                }
                else {
                    NoViableAltException nvae =
                        new NoViableAltException("27:1: stat returns [VarType value] : ( expr NEWLINE | ID '=' expr NEWLINE | NEWLINE );", 1, 2, input);

                    throw nvae;
                }
                }
                break;
            case NEWLINE:
                {
                alt1=3;
                }
                break;
            default:
                NoViableAltException nvae =
                    new NoViableAltException("27:1: stat returns [VarType value] : ( expr NEWLINE | ID '=' expr NEWLINE | NEWLINE );", 1, 0, input);

                throw nvae;
            }

            switch (alt1) {
                case 1 :
                    // Euclid.g:29:6: expr NEWLINE
                    {
                    pushFollow(FOLLOW_expr_in_stat117);
                    expr1=expr();
                    _fsp--;

                    match(input,NEWLINE,FOLLOW_NEWLINE_in_stat119); 
                     value = expr1; 

                    }
                    break;
                case 2 :
                    // Euclid.g:30:4: ID '=' expr NEWLINE
                    {
                    ID2=(Token)input.LT(1);
                    match(input,ID,FOLLOW_ID_in_stat126); 
                    match(input,19,FOLLOW_19_in_stat128); 
                    pushFollow(FOLLOW_expr_in_stat130);
                    expr3=expr();
                    _fsp--;

                    match(input,NEWLINE,FOLLOW_NEWLINE_in_stat132); 
                     value = new SymbVarType(ID2.getText(), expr3); f.setvar(ID2.getText(), expr3); 

                    }
                    break;
                case 3 :
                    // Euclid.g:31:9: NEWLINE
                    {
                    match(input,NEWLINE,FOLLOW_NEWLINE_in_stat144); 
                     value = null; 

                    }
                    break;

            }
        }
        catch (RecognitionException re) {
            reportError(re);
            recover(input,re);
        }
        finally {
        }
        return value;
    }
    // $ANTLR end stat


    // $ANTLR start expr
    // Euclid.g:34:1: expr returns [VarType value] : e= multExpr ( PLUS e= multExpr | MINUS e= multExpr )* ;
    public final VarType expr() throws RecognitionException {
        VarType value = null;

        VarType e = null;


        try {
            // Euclid.g:35:5: (e= multExpr ( PLUS e= multExpr | MINUS e= multExpr )* )
            // Euclid.g:35:9: e= multExpr ( PLUS e= multExpr | MINUS e= multExpr )*
            {
            pushFollow(FOLLOW_multExpr_in_expr171);
            e=multExpr();
            _fsp--;

             value = e; 
            // Euclid.g:36:9: ( PLUS e= multExpr | MINUS e= multExpr )*
            loop2:
            do {
                int alt2=3;
                int LA2_0 = input.LA(1);

                if ( (LA2_0==PLUS) ) {
                    alt2=1;
                }
                else if ( (LA2_0==MINUS) ) {
                    alt2=2;
                }


                switch (alt2) {
            	case 1 :
            	    // Euclid.g:36:11: PLUS e= multExpr
            	    {
            	    match(input,PLUS,FOLLOW_PLUS_in_expr185); 
            	    pushFollow(FOLLOW_multExpr_in_expr189);
            	    e=multExpr();
            	    _fsp--;

            	     value = value.add(e); 

            	    }
            	    break;
            	case 2 :
            	    // Euclid.g:37:11: MINUS e= multExpr
            	    {
            	    match(input,MINUS,FOLLOW_MINUS_in_expr203); 
            	    pushFollow(FOLLOW_multExpr_in_expr207);
            	    e=multExpr();
            	    _fsp--;

            	     value = value.subtract(e); 

            	    }
            	    break;

            	default :
            	    break loop2;
                }
            } while (true);


            }

        }
        catch (RecognitionException re) {
            reportError(re);
            recover(input,re);
        }
        finally {
        }
        return value;
    }
    // $ANTLR end expr


    // $ANTLR start multExpr
    // Euclid.g:41:1: multExpr returns [VarType value] : e= p1Expr ( MULT e= p1Expr | DIV e= p1Expr | MOD e= p1Expr )* ;
    public final VarType multExpr() throws RecognitionException {
        VarType value = null;

        VarType e = null;


        try {
            // Euclid.g:42:5: (e= p1Expr ( MULT e= p1Expr | DIV e= p1Expr | MOD e= p1Expr )* )
            // Euclid.g:42:9: e= p1Expr ( MULT e= p1Expr | DIV e= p1Expr | MOD e= p1Expr )*
            {
            pushFollow(FOLLOW_p1Expr_in_multExpr245);
            e=p1Expr();
            _fsp--;

             value = e; 
            // Euclid.g:43:6: ( MULT e= p1Expr | DIV e= p1Expr | MOD e= p1Expr )*
            loop3:
            do {
                int alt3=4;
                switch ( input.LA(1) ) {
                case MULT:
                    {
                    alt3=1;
                    }
                    break;
                case DIV:
                    {
                    alt3=2;
                    }
                    break;
                case MOD:
                    {
                    alt3=3;
                    }
                    break;

                }

                switch (alt3) {
            	case 1 :
            	    // Euclid.g:44:8: MULT e= p1Expr
            	    {
            	    match(input,MULT,FOLLOW_MULT_in_multExpr265); 
            	    pushFollow(FOLLOW_p1Expr_in_multExpr269);
            	    e=p1Expr();
            	    _fsp--;

            	     value = value.mult(e); 

            	    }
            	    break;
            	case 2 :
            	    // Euclid.g:45:8: DIV e= p1Expr
            	    {
            	    match(input,DIV,FOLLOW_DIV_in_multExpr280); 
            	    pushFollow(FOLLOW_p1Expr_in_multExpr284);
            	    e=p1Expr();
            	    _fsp--;

            	     value = value.div(e); 

            	    }
            	    break;
            	case 3 :
            	    // Euclid.g:46:8: MOD e= p1Expr
            	    {
            	    match(input,MOD,FOLLOW_MOD_in_multExpr295); 
            	    pushFollow(FOLLOW_p1Expr_in_multExpr299);
            	    e=p1Expr();
            	    _fsp--;

            	     value = value.mod(e); 

            	    }
            	    break;

            	default :
            	    break loop3;
                }
            } while (true);


            }

        }
        catch (RecognitionException re) {
            reportError(re);
            recover(input,re);
        }
        finally {
        }
        return value;
    }
    // $ANTLR end multExpr


    // $ANTLR start p1Expr
    // Euclid.g:50:1: p1Expr returns [VarType value] : e= unary ( POW e= unary )* ;
    public final VarType p1Expr() throws RecognitionException {
        VarType value = null;

        VarType e = null;


        try {
            // Euclid.g:51:2: (e= unary ( POW e= unary )* )
            // Euclid.g:51:4: e= unary ( POW e= unary )*
            {
            pushFollow(FOLLOW_unary_in_p1Expr329);
            e=unary();
            _fsp--;

             value = e; 
            // Euclid.g:52:3: ( POW e= unary )*
            loop4:
            do {
                int alt4=2;
                int LA4_0 = input.LA(1);

                if ( (LA4_0==POW) ) {
                    alt4=1;
                }


                switch (alt4) {
            	case 1 :
            	    // Euclid.g:52:5: POW e= unary
            	    {
            	    match(input,POW,FOLLOW_POW_in_p1Expr337); 
            	    pushFollow(FOLLOW_unary_in_p1Expr341);
            	    e=unary();
            	    _fsp--;

            	     value = value.pow(e); 

            	    }
            	    break;

            	default :
            	    break loop4;
                }
            } while (true);


            }

        }
        catch (RecognitionException re) {
            reportError(re);
            recover(input,re);
        }
        finally {
        }
        return value;
    }
    // $ANTLR end p1Expr


    // $ANTLR start unary
    // Euclid.g:56:1: unary returns [VarType value] : (e= atom | '-' e= atom | '~' e= atom );
    public final VarType unary() throws RecognitionException {
        VarType value = null;

        VarType e = null;


        try {
            // Euclid.g:57:2: (e= atom | '-' e= atom | '~' e= atom )
            int alt5=3;
            switch ( input.LA(1) ) {
            case LPAREN:
            case ID:
            case INT:
            case FLOAT:
            case STRING:
                {
                alt5=1;
                }
                break;
            case MINUS:
                {
                alt5=2;
                }
                break;
            case 20:
                {
                alt5=3;
                }
                break;
            default:
                NoViableAltException nvae =
                    new NoViableAltException("56:1: unary returns [VarType value] : (e= atom | '-' e= atom | '~' e= atom );", 5, 0, input);

                throw nvae;
            }

            switch (alt5) {
                case 1 :
                    // Euclid.g:57:4: e= atom
                    {
                    pushFollow(FOLLOW_atom_in_unary365);
                    e=atom();
                    _fsp--;

                     value = e; 

                    }
                    break;
                case 2 :
                    // Euclid.g:58:4: '-' e= atom
                    {
                    match(input,MINUS,FOLLOW_MINUS_in_unary372); 
                    pushFollow(FOLLOW_atom_in_unary376);
                    e=atom();
                    _fsp--;

                     value = e.negate(); 

                    }
                    break;
                case 3 :
                    // Euclid.g:59:4: '~' e= atom
                    {
                    match(input,20,FOLLOW_20_in_unary383); 
                    pushFollow(FOLLOW_atom_in_unary387);
                    e=atom();
                    _fsp--;

                     value = e.not(); 

                    }
                    break;

            }
        }
        catch (RecognitionException re) {
            reportError(re);
            recover(input,re);
        }
        finally {
        }
        return value;
    }
    // $ANTLR end unary


    // $ANTLR start atom
    // Euclid.g:62:1: atom returns [VarType value] : ( INT | FLOAT | ID | ID LPAREN args RPAREN | STRING | LPAREN expr RPAREN );
    public final VarType atom() throws RecognitionException {
        VarType value = null;

        Token INT4=null;
        Token FLOAT5=null;
        Token ID6=null;
        Token ID7=null;
        Token STRING9=null;
        List<VarType> args8 = null;

        VarType expr10 = null;


        try {
            // Euclid.g:63:5: ( INT | FLOAT | ID | ID LPAREN args RPAREN | STRING | LPAREN expr RPAREN )
            int alt6=6;
            switch ( input.LA(1) ) {
            case INT:
                {
                alt6=1;
                }
                break;
            case FLOAT:
                {
                alt6=2;
                }
                break;
            case ID:
                {
                int LA6_3 = input.LA(2);

                if ( (LA6_3==LPAREN) ) {
                    alt6=4;
                }
                else if ( ((LA6_3>=PLUS && LA6_3<=MOD)||(LA6_3>=RPAREN && LA6_3<=NEWLINE)||LA6_3==21) ) {
                    alt6=3;
                }
                else {
                    NoViableAltException nvae =
                        new NoViableAltException("62:1: atom returns [VarType value] : ( INT | FLOAT | ID | ID LPAREN args RPAREN | STRING | LPAREN expr RPAREN );", 6, 3, input);

                    throw nvae;
                }
                }
                break;
            case STRING:
                {
                alt6=5;
                }
                break;
            case LPAREN:
                {
                alt6=6;
                }
                break;
            default:
                NoViableAltException nvae =
                    new NoViableAltException("62:1: atom returns [VarType value] : ( INT | FLOAT | ID | ID LPAREN args RPAREN | STRING | LPAREN expr RPAREN );", 6, 0, input);

                throw nvae;
            }

            switch (alt6) {
                case 1 :
                    // Euclid.g:63:9: INT
                    {
                    INT4=(Token)input.LT(1);
                    match(input,INT,FOLLOW_INT_in_atom409); 
                     value = new IntVarType(INT4.getText()); 

                    }
                    break;
                case 2 :
                    // Euclid.g:64:7: FLOAT
                    {
                    FLOAT5=(Token)input.LT(1);
                    match(input,FLOAT,FOLLOW_FLOAT_in_atom419); 
                     value = new FloatVarType(FLOAT5.getText()); 

                    }
                    break;
                case 3 :
                    // Euclid.g:65:7: ID
                    {
                    ID6=(Token)input.LT(1);
                    match(input,ID,FOLLOW_ID_in_atom429); 
                     value = f.getvar(ID6.getText()); 

                    }
                    break;
                case 4 :
                    // Euclid.g:66:7: ID LPAREN args RPAREN
                    {
                    ID7=(Token)input.LT(1);
                    match(input,ID,FOLLOW_ID_in_atom439); 
                    match(input,LPAREN,FOLLOW_LPAREN_in_atom441); 
                    pushFollow(FOLLOW_args_in_atom443);
                    args8=args();
                    _fsp--;

                    match(input,RPAREN,FOLLOW_RPAREN_in_atom445); 
                     value = f.call(ID7.getText(), args8); 

                    }
                    break;
                case 5 :
                    // Euclid.g:67:7: STRING
                    {
                    STRING9=(Token)input.LT(1);
                    match(input,STRING,FOLLOW_STRING_in_atom455); 
                     value = new StringVarType(STRING9.getText().substring(1, STRING9.getText().length()-1)); 

                    }
                    break;
                case 6 :
                    // Euclid.g:68:9: LPAREN expr RPAREN
                    {
                    match(input,LPAREN,FOLLOW_LPAREN_in_atom467); 
                    pushFollow(FOLLOW_expr_in_atom469);
                    expr10=expr();
                    _fsp--;

                    match(input,RPAREN,FOLLOW_RPAREN_in_atom471); 
                     value = expr10; value.formula = "\\left(" + value.formula + "\\right)"; 

                    }
                    break;

            }
        }
        catch (RecognitionException re) {
            reportError(re);
            recover(input,re);
        }
        finally {
        }
        return value;
    }
    // $ANTLR end atom


    // $ANTLR start args
    // Euclid.g:71:1: args returns [List<VarType> value] : e= expr ( ',' e= expr )* ;
    public final List<VarType> args() throws RecognitionException {
        List<VarType> value = null;

        VarType e = null;


        try {
            // Euclid.g:72:2: (e= expr ( ',' e= expr )* )
            // Euclid.g:72:4: e= expr ( ',' e= expr )*
            {
            pushFollow(FOLLOW_expr_in_args493);
            e=expr();
            _fsp--;

             value = new ArrayList<VarType>(); value.add(e); 
            // Euclid.g:73:3: ( ',' e= expr )*
            loop7:
            do {
                int alt7=2;
                int LA7_0 = input.LA(1);

                if ( (LA7_0==21) ) {
                    alt7=1;
                }


                switch (alt7) {
            	case 1 :
            	    // Euclid.g:73:4: ',' e= expr
            	    {
            	    match(input,21,FOLLOW_21_in_args500); 
            	    pushFollow(FOLLOW_expr_in_args504);
            	    e=expr();
            	    _fsp--;

            	     value.add(e); 

            	    }
            	    break;

            	default :
            	    break loop7;
                }
            } while (true);


            }

        }
        catch (RecognitionException re) {
            reportError(re);
            recover(input,re);
        }
        finally {
        }
        return value;
    }
    // $ANTLR end args


 

    public static final BitSet FOLLOW_expr_in_stat117 = new BitSet(new long[]{0x0000000000002000L});
    public static final BitSet FOLLOW_NEWLINE_in_stat119 = new BitSet(new long[]{0x0000000000000002L});
    public static final BitSet FOLLOW_ID_in_stat126 = new BitSet(new long[]{0x0000000000080000L});
    public static final BitSet FOLLOW_19_in_stat128 = new BitSet(new long[]{0x000000000013C420L});
    public static final BitSet FOLLOW_expr_in_stat130 = new BitSet(new long[]{0x0000000000002000L});
    public static final BitSet FOLLOW_NEWLINE_in_stat132 = new BitSet(new long[]{0x0000000000000002L});
    public static final BitSet FOLLOW_NEWLINE_in_stat144 = new BitSet(new long[]{0x0000000000000002L});
    public static final BitSet FOLLOW_multExpr_in_expr171 = new BitSet(new long[]{0x0000000000000032L});
    public static final BitSet FOLLOW_PLUS_in_expr185 = new BitSet(new long[]{0x000000000013C420L});
    public static final BitSet FOLLOW_multExpr_in_expr189 = new BitSet(new long[]{0x0000000000000032L});
    public static final BitSet FOLLOW_MINUS_in_expr203 = new BitSet(new long[]{0x000000000013C420L});
    public static final BitSet FOLLOW_multExpr_in_expr207 = new BitSet(new long[]{0x0000000000000032L});
    public static final BitSet FOLLOW_p1Expr_in_multExpr245 = new BitSet(new long[]{0x00000000000001C2L});
    public static final BitSet FOLLOW_MULT_in_multExpr265 = new BitSet(new long[]{0x000000000013C420L});
    public static final BitSet FOLLOW_p1Expr_in_multExpr269 = new BitSet(new long[]{0x00000000000001C2L});
    public static final BitSet FOLLOW_DIV_in_multExpr280 = new BitSet(new long[]{0x000000000013C420L});
    public static final BitSet FOLLOW_p1Expr_in_multExpr284 = new BitSet(new long[]{0x00000000000001C2L});
    public static final BitSet FOLLOW_MOD_in_multExpr295 = new BitSet(new long[]{0x000000000013C420L});
    public static final BitSet FOLLOW_p1Expr_in_multExpr299 = new BitSet(new long[]{0x00000000000001C2L});
    public static final BitSet FOLLOW_unary_in_p1Expr329 = new BitSet(new long[]{0x0000000000001002L});
    public static final BitSet FOLLOW_POW_in_p1Expr337 = new BitSet(new long[]{0x000000000013C420L});
    public static final BitSet FOLLOW_unary_in_p1Expr341 = new BitSet(new long[]{0x0000000000001002L});
    public static final BitSet FOLLOW_atom_in_unary365 = new BitSet(new long[]{0x0000000000000002L});
    public static final BitSet FOLLOW_MINUS_in_unary372 = new BitSet(new long[]{0x000000000003C400L});
    public static final BitSet FOLLOW_atom_in_unary376 = new BitSet(new long[]{0x0000000000000002L});
    public static final BitSet FOLLOW_20_in_unary383 = new BitSet(new long[]{0x000000000003C400L});
    public static final BitSet FOLLOW_atom_in_unary387 = new BitSet(new long[]{0x0000000000000002L});
    public static final BitSet FOLLOW_INT_in_atom409 = new BitSet(new long[]{0x0000000000000002L});
    public static final BitSet FOLLOW_FLOAT_in_atom419 = new BitSet(new long[]{0x0000000000000002L});
    public static final BitSet FOLLOW_ID_in_atom429 = new BitSet(new long[]{0x0000000000000002L});
    public static final BitSet FOLLOW_ID_in_atom439 = new BitSet(new long[]{0x0000000000000400L});
    public static final BitSet FOLLOW_LPAREN_in_atom441 = new BitSet(new long[]{0x000000000013C420L});
    public static final BitSet FOLLOW_args_in_atom443 = new BitSet(new long[]{0x0000000000000800L});
    public static final BitSet FOLLOW_RPAREN_in_atom445 = new BitSet(new long[]{0x0000000000000002L});
    public static final BitSet FOLLOW_STRING_in_atom455 = new BitSet(new long[]{0x0000000000000002L});
    public static final BitSet FOLLOW_LPAREN_in_atom467 = new BitSet(new long[]{0x000000000013C420L});
    public static final BitSet FOLLOW_expr_in_atom469 = new BitSet(new long[]{0x0000000000000800L});
    public static final BitSet FOLLOW_RPAREN_in_atom471 = new BitSet(new long[]{0x0000000000000002L});
    public static final BitSet FOLLOW_expr_in_args493 = new BitSet(new long[]{0x0000000000200002L});
    public static final BitSet FOLLOW_21_in_args500 = new BitSet(new long[]{0x000000000013C420L});
    public static final BitSet FOLLOW_expr_in_args504 = new BitSet(new long[]{0x0000000000200002L});

}